// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
use anyhow::{anyhow};
use tauri::Manager;
use std::path::{self, Path};
pub mod shared;
use shared::{Shared, WorkTask};
use std::sync::Arc;
use tracing::{error, info, debug};

type SharedState = Arc<Shared>;

mod command;
pub use command::{async_get_last_png};

#[derive(Default, Debug, serde::Serialize, serde::Deserialize)]
struct CustomResponse {
  filename: String,
  other_val: usize,
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run(shared: Arc<Shared> ) {      
    tauri::Builder::default()
        .plugin(tauri_plugin_shell::init())
        .manage( shared)  // invoke_handler注册的command, sync与async的command 都可以，但需要分别注册！！！
        .invoke_handler(tauri::generate_handler![greet])
        .invoke_handler(tauri::generate_handler![hello, my_webview_command, my_app_command, async_greet, async_get_last_png])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");    
}

////////

#[tauri::command]
fn greet(state: tauri::State<'_, SharedState>, name: &str) -> Result<String,String> {   
    // State抽取案例，同步不可以！
    debug!("greet command, state.startup = {:?} ...", state.startup);       
    Ok(format!("Hello {}, tauri::State! Your state.startup is {}!", name, state.startup))
}

#[tauri::command]
async fn async_greet(state: tauri::State<'_, SharedState>, name: &str) -> Result<String,String> {   
    // State抽取案例，异步支持！
    debug!("greet command, state.startup = {:?} ...", state.startup);       
    Ok(format!("Hello {}, tauri::State! Your state.startup is {}!", name, state.startup))
}

#[tauri::command]
async fn my_webview_command(webview_window: tauri::WebviewWindow)-> Result<String, String> {
  let label = format!("{}",webview_window.label());
  debug!("WebviewWindow: {}", label);
  Ok(label)
}

#[tauri::command]
async fn my_app_command(app_handle: tauri::AppHandle)-> Result<String, ()> {
  let doc_dir = format!("{:?}", app_handle.path().document_dir());
  debug!("{:?}", doc_dir);
  Ok(doc_dir)
}

#[tauri::command]
async fn hello(state: tauri::State<'_, SharedState>, name: &str) -> Result<String, String> { //Vec<CustomResponse>  {
    let fvec = path_walk_csv(Path::new("./")).unwrap();        
    debug!("shared state.startup = {:?} ...", state.startup);
    let task = WorkTask::SendMessage("New Task".to_owned());
    if let Err(err) = state.tx.send(task).await {
        error!("Error sending task: {:?}", err);
    }    
    let retc: Vec<CustomResponse> =  fvec.into_iter().map(|x| CustomResponse{filename: x, other_val: 42}).collect();
    let s = serde_json::to_string(&retc).unwrap();
    return Ok(s);
}

pub fn path_walk_csv(path: &Path) -> anyhow::Result<Vec<String>> {
    let mut rets: Vec<String> = vec![];
    for entry in path.read_dir()? {
        if let Ok(entry) = entry {
            if let Ok(ft) = entry.file_type() {
                // .unwrap().is_dir(){
                let ename = entry
                    .file_name()
                    .as_os_str()
                    .to_str()
                    .ok_or(anyhow!("e"))?
                    .to_string();
                if ft.is_dir() {
                    // println!("inner -> {:#?}", ename);
                    if !ename.starts_with(".") {
                        let mut subf = path_walk_csv(&entry.path().as_path())?;
                        rets.append(&mut subf);
                    } else {
                        // println!("break {:#?}", ename );
                    }
                } else if ft.is_file() {
                    let fname = entry.path().display().to_string();
                    let ext = entry
                        .path()
                        .extension()
                        .unwrap_or_default()
                        .to_str()
                        .unwrap_or_default()
                        .to_lowercase();
                    if ext.len() > 2 {
                        rets.push(entry.path().display().to_string());
                    }
                }
            }
        }
    }
    Ok(rets)
}
